﻿package  {
	import flash.display.MovieClip;
	import flash.display.Stage;
	import flash.events.Event;
    import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.ui.Keyboard;
	import flash.text.TextField;
	import flash.text.*;
	
	public class Game extends MovieClip{
		//World Classes
		private var gameGrid:Grid = new Grid(); //Creates the Game Grid object
		private var fuseFact:FuseFactory = new FuseFactory(); // Creates the Fuse Factory Object
		private var soundplay:soundFx = new soundFx(); //Creates the SFX player object
		
		//Stage Variables
		private var appState:Number = 0; //Over All Game State
		private var gameState:Number = 0; //State of the Playing Stage
		private var loadTime:Number = 0; //Timer used for ready graphic
		private var gameTime:int = 0; //Used to count frames
		private const tic = 24; //Denotes the amount of frames it takes to reach 1 second
		private var level = 0; //Level of the game
		private var virusCount = 0; //Amount of FuseOrbs left on stage
		private var score = 0; //Score of the current playthrough
		private var highScore = 0; //Highest score in the data base.
		private var rotClick:Boolean = false; // Used for detecting single clicks of the rotate button.
		private var leftClick:Boolean = false; //Used in similiar fasion as rotClick
		private var rightClick:Boolean = false; //Used in similiar fasion as rotClick
		private var adjusted:Boolean = true; // Used to cycle through adjustments // true = shifted // false = no shift
		private var nanoGrp:NanoGroup; //Active NanoGroup
		private var scoreField:TextField = new TextField(); //Text Field for displaying Score
		private var scoreFormat:TextFormat = new TextFormat(); //Sets the Format of  the textField
		//In Game Quotes for Dexter
		private var dexterQuotes:Array = new Array(
"Your doing better than DeeDee at least." , "I don't know if those go there...." , "Did you hear a crash?", "I wonder where DeeDee is....");
		//In Game Quotes for Mandark
		private var mandarkQuotes:Array = new Array("I think that you should try moving that there...", "At least you're not named Susan...", "Einstein was a quack.", "I doubt Dexter could do better than that.");
		//In Game Quotes for Professor Utonium
		private var utoniumQuotes:Array = new Array("Ah very good.", "Now I think you have the idea." , "Good Job." ,"I wonder what would happen if I add those with the sugar and spice....");
		private var quoteField:TextField = new TextField(); //Text Field for displaying Character Quotes
		private var quoteFormat:TextFormat = new TextFormat();
		private var virusField:TextField = new TextField();//Text Field for displaying Virus Count
		private var virusFormat:TextFormat = new TextFormat();
		private var highScoreField:TextField = new TextField();//Text Field for displaying HighScore
		// Private Properties:
		private static var initialized:Boolean = false; //Used to determine if the game has been initialized
		
		// Initialization:
		public function Game(hScore:Number) {
			highScore = hScore;
		}
		
		//Called once in order to set up event handling
		public function initialize(stage:Stage) {
			if (!initialized) {
				initialized = false;
				stage.addEventListener(Event.ENTER_FRAME, mainFunction);
				Key.initialize(stage);
			}
		}
	
		// Public Methods:
		//Main Game Loop
		public function mainFunction(event:Event):void {
			switch(appState) {
				case 0: {
					//Display Ready graphics
					if(loadTime == 0){
						MovieClip(root).startGraphic.gotoAndPlay(2);
						loadTime++;
					} else if (loadTime < 72) {
						loadTime++;
					} else if (loadTime >= 72) {
						loadTime = 0;
						appState = 2;
					}
					break;
				}
				case 1: {
					//initialize level
					initializeLevel();
					break;
				}
				case 2: {
					//Main game loop
					mainGameFunction();
					break;
				}
				case 3: {
					//End Level Graphics Display
					if (loadTime == 0) {
						MovieClip(root).levelComplete.gotoAndPlay(2);
						loadTime++;
					} else if (loadTime != 0) {
						if (Key.isDown(Keyboard.UP)) {
							MovieClip(root).levelComplete.gotoAndStop(1);
							loadTime = 0;
							appState = 1;
						}
					}
				}
			}
		}
		// Protected Methods:
		//Refreshes the screen in order to set up the next level
		private function initializeLevel():void {
			
			for (var i:int = 0; i < gameGrid.gridArray.length; i++) {
				if (gameGrid.gridArray[i] != null) {
					removeChild(gameGrid.gridArray[i]);
				}
				gameGrid.gridArray[i] = null;
			}
			gameState = 0;
			appState = 0;
		}
		
		//The Main loop that runs through the game logic during each stage.
		private function mainGameFunction():void{
			switch(gameState) {
				//Case 0: Initializes the current Stage
				case 0: {
					if (level < 3) {
						quoteField.text = "Now, let's begin.";
						virusCount = 5;
					} else if (level >= 3 && level < 6) {
						virusCount = 15;
						quoteField.text = "So now you come crawling to me...";
						try{
							MovieClip(root).gameBG.gotoAndStop(2);
						} catch (e:Error) {
						}
					} else if (level >= 6) {
						virusCount = 25;
						quoteField.text = "The tests are complete and DeeDee is no where to be found...";
						try{
							MovieClip(root).gameBG.gotoAndStop(3);
						} catch (e:Error) {
						}
					}
					fuseFact.fillFuseArray(gameGrid, virusCount);
					//soundplay.playSound(op_sound);
					
					//Initilize the score and quotes on the screen for each level.
					scoreFormat.color = 0xFFFFFF;
					scoreFormat.font = "Candara"; 
					scoreFormat.bold = true;
					scoreFormat.size = 20;
					quoteFormat.font = "Candara";
					quoteFormat.color = 0x000000;
					quoteFormat.size = 14;
					quoteFormat.align = TextFormatAlign.CENTER;
					scoreField.x = 90;
					scoreField.y = 155;
					scoreField.selectable = false;
					highScoreField.x = 90;
					highScoreField.y = 75;
					highScoreField.selectable = false;
					quoteField.x = 535;
					quoteField.y = 115;
					quoteField.selectable = false;
					virusField.x = 40;
					virusField.y = 450;
					virusField.selectable = false;
					virusField.width = 175;
					quoteField.multiline = true;
					quoteField.width = 175;
					quoteField.wordWrap = true;
					addChild(scoreField);
					addChild(quoteField);
					addChild(highScoreField);
					addChild(virusField);
					
					virusFormat.font = "Candara";
					virusFormat.color = 0xFF0000; 
					virusFormat.size = 40;
					virusFormat.align = TextFormatAlign.CENTER;
					
					
					virusField.text = virusCount.toString();
					highScoreField.text = highScore.toString();
					scoreField.text = score.toString();
					scoreField.setTextFormat(scoreFormat);
					quoteField.setTextFormat(quoteFormat);
					virusField.setTextFormat(virusFormat);
					highScoreField.setTextFormat(scoreFormat);
					gameState = 1;
					break;
				}
				//Case 1: Draws all the orbs in the grid to the Stage
				case 1:{
					for(var i:Number=0;i<gameGrid.gridArray.length;i++){
						if(gameGrid.gridArray[i] != null){
							addChild(gameGrid.gridArray[i]);
						}
					}
					gameState = 2;
					break;
				}
				//Case 2: Generates a new Nanogroup
				case 2:{
					generateNanoGroup();
					break;
				}
				//Case 3: Listens for user input and responds Accordingly while updating NanoGroup Position
				case 3:{
					inputStage();
					break;
				}
				//Case 4: Plays Halt Noise when NanoGroup Stops and Adds NanoGroup to the grid.
				case 4:{
					soundplay.playSound(collide_sound);
					gameGrid.addNanoGroup(nanoGrp);
					nanoGrp = null;
					gameState = 5;
					break;
				}
				//Case 5: Updates The UI to remove dead orbs and rest
				case 5: {
					gameGrid.checkOrbs();
					var multiplier:int = 0;
					multiplier = gameGrid.clearDeadOrbs();//find out how many fuzes were removed
					virusCount -= multiplier;
					score += multiplier*100; //update score
					scoreField.text= score.toString(); //update the displayed score.
					scoreField.setTextFormat(scoreFormat);
					virusField.text = virusCount.toString();
					virusField.setTextFormat(virusFormat);
					highScoreField.text = highScore.toString();
					highScoreField.setTextFormat(scoreFormat);
					if(multiplier > 0){//a fuse was deleted so update what the character on screen says.
						var quoteNumber:int = Math.random() * 4;
						if (level < 3){
							quoteField.text = utoniumQuotes[quoteNumber];
							}
						else if (level >= 3 && level < 6){
							quoteField.text = mandarkQuotes[quoteNumber];
							}
						else if (level >= 6) {
							quoteField.text = dexterQuotes[quoteNumber];
							}
					}
					
					quoteField.setTextFormat(quoteFormat);//make sure text is in the same format as in the initilization
					removeDeadOrbs();
					gameState = 6;
					if (virusCount == 0) {
						gameState = 8;
					}
					break;
				}
				//Case 6: Adjusts All Unattached NanoOrbs and Unobstructed NanoGroups down one position if possible.
				case 6: {
					if (adjusted) {
						adjusted = gameGrid.adjustOrbs();
						gameState = 5;
					} else{
						gameState = 2;
						adjusted = true;
					}
					break;
				}
				//In the case of a game Over
				case 7: {
					//Game over Case
					try {
						if (score >= 8500) {
							MovieClip( root ).gotoAndStop(5);
						} else{
							MovieClip( root ).gotoAndStop(4);
						}
					} catch (error:Error) {
						//Not really an error
					}
					break;
				}
				case 8: {
					//Finish Level Case\
					level++;
					appState = 3;
					break;
				}
			}
		}
		
		//Creates a new NanoGroup that is user controlled
		private function generateNanoGroup():void {
			var tempType1:int = Math.ceil((Math.random() * 30) / 10);
			var tempType2:int = Math.ceil((Math.random() * 30) / 10);
			var nano1:NanoOrb = new NanoOrb(3,0,tempType1);
			var nano2:NanoOrb = new NanoOrb(4,0,tempType2);
			addChild(nano1);
			addChild(nano2);
			nanoGrp = new NanoGroup(nano1,nano2);
			gameState = 3;
			if (gameGrid.hasOrbThere(3, 0) || gameGrid.hasOrbThere(4, 0)) {
				gameState = 7;
			}
		}
		// INPUT PHASE of Gameplay
		private function inputStage():void {
			//NOTE: This is a good way to do button CLICK
			if (Key.isDown(Keyboard.UP) && !rotClick){
				nanoGrp.rotate(gameGrid);
				rotClick = true;
			}else if(!Key.isDown(Keyboard.UP)){
				rotClick = false;
			}
			//END NOTE: GOOD CLICK
			
			//NOTE:Move the NanoGroup Along the Y each Tic
			if(Key.isDown(Keyboard.DOWN)){
				nanoGrp.shiftDown(gameGrid);
				gameTime = 0;
				if(!nanoGrp.getInUse()){
					gameState = 4;
					//break;
				}
			} else if(gameTime == tic){
				//Move the NanoGroup
				//reset gameTime
				nanoGrp.shiftDown(gameGrid);
				gameTime = 0;
				if(!nanoGrp.getInUse()){
					gameState = 4;
					//break;
				}
			} else {
				//increate gameTime
				gameTime++;
			}
			//END NOTE: Y MOVEMENT
			
			//NOTE: Move the NanoGroup Along the X Axis
			if(Key.isDown(Keyboard.LEFT) && !leftClick){
				nanoGrp.shiftLeft(gameGrid);
				leftClick = true;
			} else if(Key.isDown(Keyboard.LEFT) && leftClick){
				if(gameTime%6 == 0){
					nanoGrp.shiftLeft(gameGrid);
				}
			} else if(!Key.isDown(Keyboard.LEFT)){
				leftClick = false;
			}
			
			if(Key.isDown(Keyboard.RIGHT)&& !rightClick && !Key.isDown(Keyboard.LEFT)){
				nanoGrp.shiftRight(gameGrid);
				rightClick = true;
			} else if(Key.isDown(Keyboard.RIGHT) && rightClick && !Key.isDown(Keyboard.LEFT)){
				if(gameTime%6 == 0){
					nanoGrp.shiftRight(gameGrid);
				}
			} else if(!Key.isDown(Keyboard.RIGHT)){
				rightClick = false;
			}
			//END NOTE: X MOVEMENT
		}
		public function getScore():int{
				return score;
			}
		//Removes dead orbs from the display list
		private function removeDeadOrbs():void{
			while(gameGrid.deadList.length != 0){
				removeChild(gameGrid.deadList.pop());
			}
		}
	}
	
}